package com.youlu.campus.service.jinshuju;

import com.google.common.collect.Lists;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.common.utils.ExcelUtil;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.domain.UserActivityTaskRankingAttachImport;
import com.youlu.campus.entity.enums.TaskBizType;
import com.youlu.campus.entity.jinshuju.JinUserBindInfo;
import com.youlu.campus.entity.jinshuju.JinUserParticipate;
import com.youlu.campus.entity.jinshuju.JinUserRank;
import com.youlu.campus.entity.jinshuju.dto.JinUserRankDTO;
import com.youlu.campus.entity.jinshuju.vo.JinUserRankVo;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.vote.SimpleActivityService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : [dengbo]
 * @className : JinShuJuUserRankService
 * @description : [金数据排行榜]
 * @createTime : [2023/6/19 15:23]
 */
@Service
@Slf4j
public class JinShuJuUserRankService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private SimpleActivityService simpleActivityService;
    @Autowired
    private ActivityService activityService;

    public void saveUserRankRecord(String activityId, String shareUserId, Integer num) {
        H5UserPO shareUser = mongoTemplate.findOne(new Query(Criteria.where("accountInfoId").is(shareUserId)), H5UserPO.class);
        if (shareUser == null) {
            log.error("share user:{} info not exist", shareUserId);
            return;
        }
        String openId = "";
        JinUserBindInfo bindInfo = mongoTemplate.findOne(new Query().addCriteria(Criteria.where("mobile").is(shareUser.getMobile())), JinUserBindInfo.class);
        if (bindInfo != null) {
            openId = bindInfo.getThirdCode();
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(shareUserId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        Update update = new Update();
        Date date = new Date();
        update.set("userId", shareUser.getAccountInfoId());
        update.set("activityId", activityId);
        update.setOnInsert("name", shareUser.getName());
        update.setOnInsert("mobile", shareUser.getMobile());
        update.setOnInsert("universityId", shareUser.getUniversityId());
        update.setOnInsert("universityName", shareUser.getUniversityName());
        update.set("nickName", shareUser.getNickName());
        update.set("avatarUrl", shareUser.getAvatarUrl());
        if (StringUtils.isNotBlank(openId)) {
            update.set("openId", openId);
        }
        update.set("updatedTime", date);
        update.setOnInsert("deleted", false);
        update.setOnInsert("createdTime", date);
        update.inc("inviteNum", 1);
        update.inc("score", num);
        FindAndModifyOptions findAndModifyOptions = new FindAndModifyOptions();
        findAndModifyOptions.returnNew(Boolean.TRUE);
        findAndModifyOptions.upsert(Boolean.TRUE);
        mongoTemplate.findAndModify(query, update, findAndModifyOptions, JinUserRank.class);
    }

    public void updateOpenId(String activityId, String userId, String openId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        Update update = new Update();
        update.set("openId", openId);
        update.set("updatedTime", new Date());
        mongoTemplate.updateFirst(query, update, JinUserRank.class);
    }

    public JinUserRank findByUserId(String activityId, String userId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        return mongoTemplate.findOne(query, JinUserRank.class);
    }


    public List<JinUserRank> findByUserIds(String activityId, List<String> userIds) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").in(userIds));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        return mongoTemplate.find(query, JinUserRank.class);
    }

    public boolean shareMore3(String activityId, String userId) {
        JinUserRank rank = findByUserId(activityId, userId);
        return rank != null && rank.getInviteNum() >= 3;
    }

    public List<JinUserRankVo> getRankList(JinUserRankDTO req) {
        List<String> fields = Lists.newArrayList("id", "name", "valueAlias");
        ActivityInfo activityInfo = simpleActivityService.findFieldsById(req.getActivityId(), fields, ActivityInfo.class);
        if (Objects.isNull(activityInfo)) {
            throw new BusinessException("活动不存在");
        }
        if (req.getPage() * req.getPageSize() > 100) {
            return Collections.emptyList();
        }
        Query query = new Query().addCriteria(Criteria.where("activityId").is(req.getActivityId()));
        query.addCriteria(Criteria.where("deleted").is(false));
        PageRequest request = PageRequest.of(req.getPage() - 1, req.getPageSize());
        query.with(request);
//        query.with(new Sort(Sort.Direction.DESC, "score"));
        Sort sort=Sort.by(Sort.Direction.DESC, "score");
        query.with(sort);
        List<JinUserRank> list = mongoTemplate.find(query, JinUserRank.class);
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        List<String> opList = list.stream().filter(item -> item.getOpenId() != null).distinct().map(JinUserRank::getOpenId)
                .collect(Collectors.toList());
        Map<String, WechatH5UserPO> userMap;
        if (CollectionUtils.isNotEmpty(opList)) {
            List<WechatH5UserPO> userPOS = mongoTemplate.find(new Query(Criteria.where("openId").in(opList)), WechatH5UserPO.class);
            userMap = userPOS.stream().collect(Collectors.toMap(WechatH5UserPO::getOpenId, Function.identity(), (o1, o2) -> o2));
        } else {
            userMap = new HashMap<>();
        }
        return list.stream().map(item -> {
            JinUserRankVo vo = new JinUserRankVo();
            vo.setName(item.getName());
            vo.setAvatarUrl(item.getAvatarUrl());
            vo.setNickName(item.getNickName());
            if (StringUtils.isNotBlank(item.getOpenId())) {
                WechatH5UserPO po = userMap.get(item.getOpenId());
                if (po != null) {
                    String logoUrl = po.getAvatarUrl();
                    if (StringUtils.isNotBlank(logoUrl) && !logoUrl.startsWith("https://thirdwx.qlogo.cn")) {
                        vo.setAvatarUrl(po.getAvatarUrl());
                    }
                    if (StringUtils.isNotBlank(po.getNickName())) {
                        vo.setNickName(po.getNickName());
                    }
                }
            }
            if (StringUtils.isNotBlank(item.getRankAvatarUrl())) {
                vo.setAvatarUrl(item.getRankAvatarUrl());
            }
            if (StringUtils.isNotBlank(item.getRankNickName())) {
                vo.setNickName(item.getRankNickName());
            }
            vo.setUniversityName(item.getUniversityName());
            vo.setScore(item.getScore());
            vo.setScoreName(activityInfo.getValueAlias());
            vo.setInviteNum(item.getInviteNum());
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 导入贡献值
     * @param inputStream
     * @param fileName
     * @param activityId
     * @param comments
     * @param userName
     * @return
     */
    public Map<String, Object> qImport(byte[] inputStream, String fileName,
                                       String activityId, String comments, String userName) {
        log.info(":>>> 用户:{} 开始导入活动:{} 贡献值,备注:{}", userName, activityId, comments);
        Date date = new Date();
        try {
            Map<String, Object> result = new HashMap<>();
            List<UserActivityTaskRankingAttachImport> models = ExcelUtil.readData(new ByteArrayInputStream(inputStream), UserActivityTaskRankingAttachImport.class);
            result.put("allCount", models.size());
            int matchCount = 0;
            int notMatchCount = 0;
            int errorInfo = 0;
            List<Integer> notMatchRows = new ArrayList<>();
            for (int i = 0; i < models.size(); i++) {
                UserActivityTaskRankingAttachImport model = models.get(i);
                log.info(":>>> 姓名 {} 电话:{} 贡献值:{}", model.getName(), model.getMobile(), model.getQ());
                if (StringUtils.isBlank(model.getName()) || StringUtils.isBlank(model.getMobile()) || Objects.isNull(model.getQ()) ||
                        model.getMobile().length() < 10) {
                    log.error(":>>> 导入参数错误:电话、贡献值、姓名为空,手机号格式错误");
                    errorInfo++;
                    continue;
                }
                Query queryUser =
                        new Query().addCriteria(Criteria.where("mobile").is(model.getMobile())).addCriteria(Criteria.where("activityId").is(activityId));
                JinUserParticipate jinUp = this.mongoTemplate.findOne(queryUser, JinUserParticipate.class);
                if (Objects.isNull(jinUp)) {
                    continue;
                }
                H5UserPO shareUser = mongoTemplate.findOne(new Query(Criteria.where("accountInfoId").is(jinUp.getUserId())), H5UserPO.class);
                if (shareUser == null) {
                    log.error("share user:{} info not exist", jinUp.getUserId());
                    continue;
                }
                String openId = "";
                JinUserBindInfo bindInfo = mongoTemplate.findOne(new Query().addCriteria(Criteria.where("mobile").is(shareUser.getMobile())), JinUserBindInfo.class);
                if (bindInfo != null) {
                    openId = bindInfo.getThirdCode();
                }

                Query query = new Query().addCriteria(Criteria.where("userId").is(jinUp.getUserId()).and("activityId").is(activityId));
                JinUserRank da = mongoTemplate.findOne(query, JinUserRank.class);
                if (Objects.isNull(da)) {
                    da = new JinUserRank();
                    da.setOpenId(openId);
                    da.setMobile(model.getMobile());
                    da.setName(shareUser.getName());
                    da.setUniversityId(shareUser.getUniversityId());
                    da.setUniversityName(shareUser.getUniversityName());
                    da.setNickName(shareUser.getNickName());
                    da.setAvatarUrl(shareUser.getAvatarUrl());
                    da.setActivityId(activityId);
                    da.setScore(model.getQ().intValue());
                    da.setCreatedTime(date);
                    da.setUserId(jinUp.getUserId());
                    da.setInviteNum(0);
                    da.setDeleted(false);
                    mongoTemplate.insert(da);
                } else {
                    Update update = new Update();
                    update.inc("score", model.getQ());
                    update.set("updatedTime", date);
                    mongoTemplate.updateFirst(query, update, JinUserRank.class);
                }
            }

            result.put("matchCount", matchCount);
            result.put("notMatchCount", notMatchCount);
            result.put("notMatchRows", notMatchRows);
            result.put("errorInfo", errorInfo);
            result.put("tips", "列序号从0(A列)开始,第1列姓名(A列)、第2列(B列)手机号、第3列(C列)贡献值不能为空!");
            return result;
        } catch (Exception e) {
            log.error(":>>> 导入金数据贡献值错误 error fileName {}", fileName, e);
            return null;
        }
    }

}
